package com.xunk.scene.service;

import cn.hutool.core.util.IdUtil;
import com.xunk.common.redis.service.RedisService;
import com.xunk.scene.constant.SceneConstant;
import com.xunk.scene.domain.SceneConditionEquipment;
import com.xunk.scene.mapper.SceneConditionEquipmentMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @ProjectName: HIM
 * @Package: com.xunk.scene.service
 * @ClassName: ConditionEquipmentComponent
 * @Author: luanzhiwei
 * @Description: 服务启动时，将设备条件加载到redis中
 * @Date: 2021/5/8 13:24
 * @Version: 1.0
 */
@Component
@Slf4j
public class ConditionEquipmentComponent implements ApplicationRunner {
    private final ReentrantLock mainLock = new ReentrantLock();

    @Autowired
    private SceneConditionEquipmentMapper mapper;
    @Autowired
    private RedisService redisService;

    /**
     * 添加设备条件到redis
     *
     * @param value
     * @return
     */
    public boolean addToRedis(Set<String> value) {
        if (CollectionUtils.isEmpty(value)) {
            log.info("设备条件添加到redis set中，实际设备条件为空");
            return true;
        }
        String uuid = IdUtil.randomUUID();
        redisService.tryLock(SceneConstant.EQUIPMENT_CONDITION_OPERATION, uuid, 10 * 60, true);
        final ReentrantLock addLock = this.mainLock;
        addLock.lock();
        try {
            redisService.redisTemplate.opsForSet().add(SceneConstant.EQUIPMENT_CONDITION_SET, value.toArray());
            return true;
        } catch (Exception e) {
            log.error("添加设备条件到redis set中异常{}", e.getMessage());
            return false;
        } finally {
            addLock.unlock();
            redisService.unlock(SceneConstant.EQUIPMENT_CONDITION_OPERATION, uuid);
        }
    }

    /**
     * 删除设备条件
     *
     * @param value
     * @return
     */
    public boolean removeFromRedis(Set<String> value) {
        if (CollectionUtils.isEmpty(value)) {
            log.info("设备条件从redis set中删除，实际设备条件为空");
            return true;
        }
        String uuid = IdUtil.randomUUID();
        redisService.tryLock(SceneConstant.EQUIPMENT_CONDITION_OPERATION, uuid, 10 * 60, true);
        final ReentrantLock addLock = this.mainLock;
        addLock.lock();
        try {
            redisService.redisTemplate.opsForSet().remove(SceneConstant.EQUIPMENT_CONDITION_SET, value.toArray());
            return true;
        } catch (Exception e) {
            log.error("设备条件从redis set中删除异常{}", e.getMessage());
            return false;
        } finally {
            addLock.unlock();
            redisService.unlock(SceneConstant.EQUIPMENT_CONDITION_OPERATION, uuid);
        }
    }

    /**
     * 判断是否存在
     *
     * @param value
     * @return
     */
    public boolean exist(String value) {
        return redisService.redisTemplate.opsForSet().isMember(SceneConstant.EQUIPMENT_CONDITION_SET, value);
    }

    /**
     * Callback used to run the bean.
     *
     * @param args incoming application arguments
     * @throws Exception on error
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("项目启动，加载设备条件表到redis set中");
        String uuid = IdUtil.randomUUID();
        if (!redisService.tryLock(SceneConstant.EQUIPMENT_CONDITION_OPERATION, uuid, 10 * 60, false)) {
            log.info("未抢到锁，由其他服务器加载设备条件表到redis set中");
            return;
        }
        log.info("加载设备条件表到redis set中,抢锁成功");
        //删除
        redisService.deleteObject(SceneConstant.EQUIPMENT_CONDITION_SET);
        SceneConditionEquipment conditionEquipment = new SceneConditionEquipment();
        conditionEquipment.setDelFlag(SceneConstant.DEL_N);
        List<SceneConditionEquipment> list = mapper.selectEquipmentConditionList(conditionEquipment);
        Set<String> collect = list.stream().map(item -> item.getDeviceSn() + SceneConstant.SEPARATOR_EQUIPMENT + item.getDeviceProp()).collect(Collectors.toSet());
        log.info("缓存{}条数据", collect.size());
        //重新缓存
        redisService.setCacheSet(SceneConstant.EQUIPMENT_CONDITION_SET, collect);
        Boolean unlock = redisService.unlock(SceneConstant.EQUIPMENT_CONDITION_OPERATION, uuid);
        log.info("加载设备条件表到redis set中,移除redis锁结果：{}", unlock);
    }
}
